void sqlite3Update( Parse *pParse, /* The parser context */ SrcList *pTabList, /* The table in which we should change things */ ExprList *pChanges, /* Things to be changed */ Expr *pWhere, /* The WHERE clause. May be null */ int onError /* How to handle constraint errors */ )
函数介绍:这是一个更新函数。
此函数有以下几部分组成:
1)寄存器分配。 2)到我们想要更新的表。 3)找出如果有触发器并且更新的这个表是一个视图。 4)给主要的数据库表和所有的目录分配指针,索引的指针可能不被使用,但是如果使用索引的指针,他们应该发生在数据库指针的右面,所以继续分配足够的空间以备不时之需。 5)初始化上下文的名称。 6)解决更新语句所有表达式的列名,并且在pChange数组中找到要更新的每一个列的列索引,于每一个要更新的列,确保我们有权限改变列。 7)为数组aRegIdx[]分配内存,对于被更新表的每个索引,在这个数组中都有一个入口,填写的值的寄存器数量指数使用和未使用的指数为零。 8)开始生成代码。 9)虚拟表必须单独处理。 10)分配所需的寄存器。 11)开始解析上下文。 12)如果我们尝试更新一个视图,必须要注意到视图是一个临时表。 13)解决where子句所有表达式的列名。 14)开始扫描数据库。 15)着要被更新的每一项的rowid。 16)结束数据库的扫描循环。 17)初始化更新的行数。 18)打开每个需要更新的索引,需要注意的是如果任何索引都能够潜在的调用REPLACE冲突,那么我们需要打开所有的指标,因为我们可能需要删除一些记录。 19)置顶更新循环。 20)游标iCur 指向要被更新的记录,如果此记录出于某种原因不存在(触发器程序引起的删除,比如跳转到RowSet循环的下一次迭代)。 21)果记录号码改变,设置寄存器regNewRowid 包含新值。如果记录号没有被修改,那么regNewRowid 与regOldRowid 是同一寄存器,并且已经被填充 22)如果该表上存在触发器,用old.* column 的数据来填充寄存器数组。 23)这个分支加载的列值不会在寄存器中改变,这种情况在以下条件下发生:没有BEFORE 触发器,或者有一个/多个BEFORE 触发器通过触发器程序使用这个值。 24)除BEFORE触发器,这发生在约束验证之前,有人认为这是错误的。 25)触发器可能已经删除了要更新的行,在这种情况下跳转到下一行。不更新或者AFTER 触发器是必须的。当被更新的行被删除或者被BEFORE 触发器重新命名,这种行为在文档中未定义。 26)如果不删除它,行触发器仍可能修改被修改行的某些列,如果出现这种情况,加载所有列值不会被UPDATE 语句修改进他们的寄存器27)做约束检查。 28)做外键约束检查。 29)删除与当前记录相关联的索引条目。。 30)如果更新记录号,删除旧的记录 31)插入新的索引条目和新记录。 32)通 过引用被删除行的外键执行任何处理行 (可能在其他表中) 的CASCADE,SET NULL 或SET DEFAULT 操作。 33)递增行计数器。 34)对下一个要更行的记录重复上述操作,直到被WHERE 子句中选择的所有的记录被更新。 35)关闭所有表 36)通过存储在插入到自动增量的表记录到的最大的rowid计数器值的内容更新sqlite_sequence表。。 37)返回被删除行的编号,如果这个过程正在生成代码是因为调用了函数sqlite3NestedParse(),没有调用回滚函数 38)确保它是一个视图以及它上边没有定义的其他宏定义,要不然它们这个文件中其他功能的汇编(或者在另一文件中,如果这个文件成为合并的一部分)